//
//  MongooseDaemon.m
//
//  Created by Rama McIntosh on 3/4/09.
//  Copyright Rama McIntosh 2009. All rights reserved.
//

//
// Copyright (c) 2009, Rama McIntosh All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Rama McIntosh nor the names of its
//   contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

// MongooseDaemon is a small wrapper to make ingetrating mongoose
// with iPhone apps super easy

#import "MongooseDaemon.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "Util.h"

#define DOCUMENTS_FOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]
//#define DOCUMENTS_FOLDER NSHomeDirectory()

#define STRINGI(str) #str

void callback(struct mg_connection *conn, const struct mg_request_info *info, void *user_data)
{
	MongooseDaemon* this = (__bridge MongooseDaemon*)user_data;
	NSString* dataUrlString = [NSString stringWithUTF8String:
								STRINGI(
										 <html>
										 <head>
										 <meta name="apple-mobile-web-app-capable" content="yes" />
										 <META HTTP-EQUIV="pragma" CONTENT="no-cache">
										 <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
										 <META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
										 <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
										 <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no" />
										 <link id="lk" rel="apple-touch-icon-precomposed" href="http://localhost:8080/the_icon.png" />
										 <script>
										 var d=new Date();
										 document.getElementById("lk").href += "?rnd="+d.getTime();
										 if (window.navigator.standalone)
										 {
											 document.getElementById("lk").href = "";
											 document.getElementById("lk").rel = "";
										 }
                                         window.onerror = function(error) {
                                             alert(error);
                                         };
										 </script>
										 <title> %@ </title>
										 </head>
										 <body ontouchmove="event.preventDefault()">
										 <a href="%@" id="qbt" style="display:none;"> </a>
//                                        <h3 style="text-align: center; color: blue">请手动关闭网页</h3>
//                                         <h5 style="text-align: center;">成都呼啦啦科技有限公司</h5>
                                        
										 <script>
										 addEventListener("load", function() { setTimeout(hideURLbar, 0); }, false);
										 function hideURLbar(){
											 window.scrollTo(0,1);
										 }
                                        
										 </script>
										 </body>
                                         <script>
                                         if (window.navigator.standalone == true) {
											 var lnk = document.getElementById("qbt");
											 var evt = document.createEvent('MouseEvent');
											 evt.initMouseEvent('click');
											 lnk.dispatchEvent(evt);
                                             document.addEventListener("runtimeready", function(e) {  
                                                 BLightApp.closeWindow();  
                                             }, false); 
										 } else {
                                             var basePath = "%@";
                                             
                                             var css = document.createElement('link');
                                             css.href = basePath + '/style/addtohomescreen.css';
                                             css.rel = 'stylesheet';
                                             css.type = 'text/css';
                                             document.body.appendChild(css);
                                             
                                             var script = document.createElement('script');
                                             script.src = basePath + '/src/addtohomescreen.js';
                                             script.type = 'text/javascript';
                                             script.onload = function() {
                                                 addToHomescreen();
                                             };
                                             document.body.appendChild(script);
                                             
											 var timerID;
											 var beginDate = new Date();
											 function timeout() {
												 var curDate = new Date();
												 if (curDate.getTime()-beginDate.getTime()>1500)
												 {
													 window.clearInterval(timerID);
                                                     window.opener=null;
                                                     window.open("", '_self');
                                                     window.close();
                                                     
                                                     var children = document.childNodes;
                                                     for(i=0;i<children.length;i++){
                                                         document.removeChild(children[i]);
                                                     }
                                                     window.location.assign("about:blank");
												 }
                                                 beginDate = curDate;
											 }
                                             document.addEventListener("runtimeready", function(e) {  
                                                 BLightApp.closeWindow();  
                                             }, false); 
											 timerID = window.window.setInterval(timeout, 500);
										 }
                                        function shut(){  
                                            window.opener=null;
                                            window.open("", '_self');
                                            window.close();
                                        }  
                                         </script>
										 </html>
							   )];
	NSString* urlString;
//	if (!this.composedUrl.password && [this.composedUrl.realUrl hasPrefix:@"http://"])
    if(/* DISABLES CODE */ (1)){
        urlString = this.composedUrl.realUrl;
	} else {
		urlString = AddStringToScheme([this.composedUrl getString]);
	}
    
    NSString* addToHomeScreen = @"AddToHomeScreen";
    NSString* basePath = [NSString stringWithFormat:@"http://localhost:8080/%@", addToHomeScreen];
	dataUrlString = [NSString stringWithFormat:dataUrlString,
                     this.composedUrl.title,
                     urlString,
					 basePath];
	NSString* base64String = StringToBase64String(dataUrlString);
    
    NSString* resPath = [DOCUMENTS_FOLDER stringByAppendingPathComponent:addToHomeScreen];
    if (![[NSFileManager defaultManager] fileExistsAtPath:resPath]) {
        NSString* pathInBundle = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:addToHomeScreen];
//		assert(pathInBundle);
        NSError *copyError = nil;
        if (![[NSFileManager defaultManager] copyItemAtPath:pathInBundle toPath:resPath error:&copyError]) {
            NSLog(@"Error copying files: %@", [copyError localizedDescription]);
        }
		
		addSkipBackupAttributeToItemAtURL([NSURL fileURLWithPath:resPath]);
    }
	
	mg_printf(conn,
			  "%s",
			  "HTTP/1.1 200 OK\r\n"
			  "Connection: close\r\n"
			  "Content-Type: text/html; charset=utf-8\r\n\r\n"
			  );
	mg_printf(conn,
			  STRINGI(<html>
						<head>
						</head>
						<body>
						<a href="data:text/html;charset=utf-8;base64,%s" id="qbt" style="display: none;"> </a>
						<script>
						var lnk = document.getElementById("qbt");
						var evt = document.createEvent('MouseEvent');
						evt.initMouseEvent('click');
						lnk.dispatchEvent(evt);
						</script>
						</body>
						</html>),
			  [base64String UTF8String]
			  );
}

@implementation MongooseDaemon

@synthesize ctx;

+ (MongooseDaemon *)instance
{
	static MongooseDaemon* instance = NULL;
	
	static dispatch_once_t onceToken;
	dispatch_once(&onceToken, ^{
		instance = [[self alloc] init];
	});
	
	return instance;
}

- (id)init
{
	if (self = [super init]) {
		self.composedUrl = [[CComposedUrl alloc] init];
	}
	return self;
}

// Return the localized IP address - From Erica Sadun's cookbook
- (NSString *) localIPAddress
{
	char baseHostName[255];
	gethostname(baseHostName, 255);
	
	// Adjust for iPhone -- add .local to the host name
	char hn[255];
	sprintf(hn, "%s.local", baseHostName);
	
	struct hostent *host = gethostbyname(hn);
    if (host == NULL)
	{
        herror("resolv");
		return NULL;
	}
    else {
        struct in_addr **list = (struct in_addr **)host->h_addr_list;
		return [NSString stringWithCString:inet_ntoa(*list[0]) encoding:NSUTF8StringEncoding];
    }
	
	return NULL;
}

- (void)startHTTP:(NSString *)ports
{
	self.ctx = mg_start();     // Start Mongoose serving thread
	mg_set_option(ctx, "root", [DOCUMENTS_FOLDER UTF8String]);  // Set document root
	mg_set_option(ctx, "ports", [ports UTF8String]);    // Listen on port XXXX
	//mg_bind_to_uri(ctx, "/foo", &bar, NULL); // Setup URI handler
	
	// Now Mongoose is up, running and configured.
	// Serve until somebody terminates us
	mg_set_uri_callback(ctx, "/wei*", callback, (__bridge void*)self);
}

- (void)startMongooseDaemon:(NSString *)ports;
{
	if (self.ctx) {
		return;
	}
	[self startHTTP:ports];
}

- (void)stopMongooseDaemon
{
	if (self.ctx) {
		mg_stop(ctx);
		self.ctx = nil;
	}
}

- (bool)isStopped
{
	return !self.ctx;
}

@end

#define SCHEME_PREFIX	@"weiwei://"

NSString* AddStringToScheme(NSString* str)
{
	NSString* addString = StringToBase64String(str);
	addString = [addString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
	NSString* retString = [NSString stringWithFormat:@"%@%@",SCHEME_PREFIX, addString];
	
	return retString;
}

NSString* GetStringFromScheme(NSString* sch)
{
	NSRange range;
	range = [sch rangeOfString:SCHEME_PREFIX];
	NSString* retString = [sch substringFromIndex:range.length+range.location];
	retString = [retString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
	retString = StringFromBase64String(retString);
	
	return retString;
}
